package study2018.com.xtianzhuang.www.luncene;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.Version;

public class SearchUtil {
	private String[] ids = {
			"1", "2", "3", "4", "5", "6"
	};
	private String[] emails = {
			"soukenan@qq.com", "li@soukenan.com", "804632564@qq.com", "admin@qq.com", "soukenan@kenan.org", "123@df.com"
	};
	private String[] content = {
			"Welcome to Kenan my home", "Hello Kenan ", "Good morning", "Are you OK?", "Yeah hahahahahahaha Kenan", "I like foot ball"
	};
	private int[] attachs = {
			1, 4, 6, 2, 3, 8
	};
	private Date[] dates = null;
	private String[] names = {
			"5555", "333", "44", "111", "222", "666"
	};
	// 词典
	private Directory directory = null;
	// 写入笔
	private IndexWriter writer = null;
	// 文档对象
	private Document doc = null;
	// 读取对象
	private IndexReader reader = null;
	private IndexSearcher searcher = null;

	private void datesInit() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		dates = new Date[6];
		try {
			dates[0] = sdf.parse("2010-12-01");
			dates[1] = sdf.parse("2011-12-01");
			dates[2] = sdf.parse("2001-12-01");
			dates[3] = sdf.parse("2013-12-01");
			dates[4] = sdf.parse("2003-12-01");
			dates[5] = sdf.parse("2014-12-01");
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public SearchUtil() {
		datesInit();
		try {
			directory = FSDirectory.open(new File("D:\\study\\luncene\\index01"));
			buildIndex();
			this.getSearcher();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 构建索引
	 */
	public void buildIndex() {
		try {
			IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
			config.setOpenMode(OpenMode.CREATE);
			writer = new IndexWriter(directory, config);
			for (int i = 0; i < 6; i++) {
				doc = new Document();
				doc.add(new Field("id", ids[i], Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
				doc.add(new Field("email", emails[i], Field.Store.YES, Field.Index.NOT_ANALYZED));
				doc.add(new Field("content", this.content[i], Field.Store.NO, Field.Index.ANALYZED));
				doc.add(new Field("name", this.names[i], Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
				// 给数字加索引
				doc.add(new NumericField("attach", Field.Store.YES, true).setIntValue(attachs[i]));
				// 给日期加索引
				doc.add(new NumericField("date", Field.Store.YES, true).setLongValue(dates[i].getTime()));
				writer.addDocument(doc);
			}
		} catch (CorruptIndexException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
				} catch (CorruptIndexException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	public IndexSearcher getSearcher() {
		try {
			if (reader == null) {
				reader = IndexReader.open(directory);
			} else {
				IndexReader ir = IndexReader.openIfChanged(reader);
				if (ir != null) {
					reader.close();
					reader = ir;
				}
			}
			searcher = new IndexSearcher(reader);
			return searcher;
		} catch (CorruptIndexException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	public void termQuery(String field, String name, int num) {
		Query query = new TermQuery(new Term(field, name));
		try {
			TopDocs tds = this.searcher.search(query, num);
			System.out.println("termQuery 查询到的结果数:" + tds.totalHits);
			for (ScoreDoc sd : tds.scoreDocs) {
				doc = this.searcher.doc(sd.doc);
				System.out.println("id:" + doc.get("id") + "---" + "name:" + doc.get("name") + "---" + "attachs:" + doc.get("attach") + "---" + "email:"
						+ doc.get("email"));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				this.searcher.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 
	 * @param field 要查询的域
	 * @param lowerTerm 开始的字符
	 * @param upperTerm 结束的字符
	 * @param num 查询的top个数
	 * @param includeLower 是否包含开始的边界
	 * @param includeUpper 是否包含结束的边界
	 */
	public void termRangeQuery(String field, String lowerTerm, String upperTerm, int num, boolean includeLower, boolean includeUpper) {

		Query query = new TermRangeQuery(field, lowerTerm, upperTerm, includeLower, includeUpper);
		try {
			TopDocs tds = this.searcher.search(query, num);
			System.out.println("termRangeQuery 查询到的结果数:" + tds.totalHits);
			for (ScoreDoc sd : tds.scoreDocs) {
				doc = this.searcher.doc(sd.doc);
				System.out.println("id:" + doc.get("id") + "---" + "name:" + doc.get("name") + "---" + "attachs:" + doc.get("attach") + "---" + "email:"
						+ doc.get("email"));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				this.searcher.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 
	 * @param field
	 * @param min
	 * @param max
	 * @param num
	 * @param minInclusive
	 * @param maxInclusive
	 */
	public void queryByNumericRange(String field, int min, int max, int num, boolean minInclusive, boolean maxInclusive) {
		Query query = NumericRangeQuery.newIntRange(field, min, max, minInclusive, maxInclusive);
		try {
			TopDocs tds = this.searcher.search(query, num);
			System.out.println("queryByNumericRange 查询到的结果数:" + tds.totalHits);
			for (ScoreDoc sd : tds.scoreDocs) {
				doc = this.searcher.doc(sd.doc);
				System.out.println("id:" + doc.get("id") + "---" + "name:" + doc.get("name") + "---" + "attachs:" + doc.get("attach") + "---" + "email:"
						+ doc.get("email"));
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				this.searcher.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}